Channel 类

Info

之前提到过在 NIO 中一个连接就是使用一个 channel 表示,也就是一个通道可以表示一个底层的文件描述符,比如硬件设备、文件、网络连接等。其实不止如此,除了了对应底层的文件描述符外,Java NIO 的通道还可以细化到不同的网络传输协议,对于不同的协议 Java NIO 都有不同的实现。

Channel 的主要类型

Channel 使用比较多的类型主要有四种

名称 说明 备注
FileChannel 文件通道,主要用于文件读写 只有阻塞模式,因为对于文件的读写不需要去轮询内核数据是否准备好
SocketChannel 用于 socket 套接字 TCP 链接的数据读写 在客户端和服务端都存在
ServerSocketChannel 服务器套接字通道,允许程序监听 TCP 连接请求,为每个监听到的请求创建一个 SocketChannel 通道 只存在于服务端
DatagramChannel 用于 UDP 协议的数据读写

FileChannel 文件通道

获取 filechannel 通道

可以通过文件的输入流、输出流获取FileChannel通道,又或者通过RandomAccessFile文件随机访问类获取通道

1680087161

从filechannel通道中读取数据

在大部分的应用场景中,从通道读取数据都会调用通道的int read 写入到Buffer 中,也就是之前说过的ByteBufferbuf方法,它将从通道的读取的数据写入到ByteBuffer缓冲区中

从FileChannel中读取数据代码示例

注意

通道读取数据对于Buffer缓冲区来说是写入数据,此时缓冲区处于写入模式

写入filechannel通道

同样的大部分应用场景在往通道写入数据时是int write (ByteBufferbuf) 方法,此时缓冲区就是写入数据的来源。通过调用write()方法从Buffer中读取数据,然后写入到通道中,返回值就是写入成功的字节数

写入FileChannel通道代码示例

注意

在向通道中写入数据时要求缓冲区是可读的,需要缓冲区翻转成读模式。

在使用完通道后一定要关闭通道,使用close即可

channel.close

强制刷新到磁盘

在将缓冲数据写入通道时,出于对性能考虑,操作系统不能每次都实时将数据写入磁盘。如果需要保证将缓冲数据立刻写入磁盘需要调用force()方法强制刷新到磁盘

channel.force(true)

SocketChannel 套接字通道

在 NIO 中 SocketChannel 与 ServerSocketChannel 是相辅相成的,一个负责连接传输,一个负责连接监听。他们两个都支持阻塞和非阻塞两种模式。调用 socketChannel.configureBlocking(Boolean) 方法即可修改模式,考虑到效率方面,阻塞模式基本不会使用到。

获取 SocketChannel 通道

客户端获取通道

  1. 通过 SocketChannel 的 open 方法获得一个传输通道
  2. 将 socket 设置为非阻塞模式
  3. 对服务器 IP 和端口发起连接

1680087190

服务器端获取套接字

通过调用服务器端 ServerSocketChannel 监听套接字的 accept() 方法,来获取新连接的套接字通道

20230328